# catgirl_gui.py
import tkinter as tk
import re
from tkinter import scrolledtext, ttk, messagebox, filedialog
import os
import logging
import threading
from catgirl_center import CatgirlAssistant  # 复用对话中枢

# 配置日志输出到控制台
logging.basicConfig(
    level=logging.DEBUG,
    format='[调试] %(asctime)s - %(module)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

# -------------------------- GUI界面模块 --------------------------
class CatgirlGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("🐾 猫娘AI助手")
        self.root.geometry("700x600")
        self.root.resizable(width=True, height=True)
        self.root.configure(bg="#f8f5f9")

        # 初始化对话中枢（复用catgirl_center的实现）
        self.assistant = CatgirlAssistant(
            model="Catgirl_Assistant:v2.0",
            rag_dataset_ids=["eb7c54a2956911f0be8636bfaf29e47a"]
        )

        self.rpg_save_dir = os.path.abspath(".")
        self.loading_start_pos = None  # 记录加载提示的起始位置
        self._create_widgets()

    def _create_widgets(self):
        """创建所有界面组件"""
        # 聊天记录标题
        self.history_label = ttk.Label(
            self.root,
            text="🐱 聊天记录",
            background="#f8f5f9",
            font=("微软雅黑", 10, "bold")
        )
        self.history_label.pack(pady=(10, 5), anchor="w", padx=20)

        # 聊天记录文本框
        self.history_text = scrolledtext.ScrolledText(
            self.root,
            width=80,
            height=20,
            font=("微软雅黑", 9),
            bg="#ffffff",
            fg="#333333",
            wrap=tk.WORD,
            state=tk.DISABLED,
            relief=tk.FLAT,
            padx=10,
            pady=10
        )
        # 配置消息样式
        self.history_text.tag_configure("user_tag", foreground="#ff6b8e", font=("微软雅黑", 9, "bold"), spacing3=10)
        self.history_text.tag_configure("assistant_tag", foreground="#6b8eff", font=("微软雅黑", 9, "bold"), spacing3=10)
        self.history_text.tag_configure("system_tag", foreground="#888888", font=("微软雅黑", 8), spacing3=10)
        self.history_text.tag_configure("loading_tag", foreground="#888888", font=("微软雅黑", 8, "italic"), spacing3=10)

        self.history_text.pack(padx=20, pady=(0, 10), fill=tk.BOTH, expand=True)

        # 输入区域
        self.input_frame = ttk.Frame(self.root, style="Input.TFrame")
        self.input_frame.pack(padx=20, pady=(0, 15), fill=tk.X)

        self.input_text = tk.Text(
            self.input_frame,
            width=70,
            height=3,
            font=("微软雅黑", 9),
            bg="#ffffff",
            fg="#333333",
            wrap=tk.WORD
        )
        self.input_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))
        self.input_text.focus()

        self.button_frame = ttk.Frame(self.input_frame)
        self.button_frame.pack(side=tk.RIGHT)

        self.send_btn = ttk.Button(
            self.button_frame,
            text="发送",
            command=self._handle_send,
            style="Send.TButton"
        )
        self.send_btn.pack(pady=(0, 5), fill=tk.X)

        self.path_btn = ttk.Button(
            self.button_frame,
            text="RPG保存路径",
            command=self._choose_rpg_dir,
            style="Path.TButton"
        )
        self.path_btn.pack(fill=tk.X)

        self._configure_styles()
        self.input_text.bind("<Return>", self._on_enter_send)

    def _configure_styles(self):
        style = ttk.Style()
        style.configure("Input.TFrame", background="#f8f5f9")

        style.configure(
            "Send.TButton",
            background="#ff85a2",
            foreground="#ffffff",
            font=("微软雅黑", 9, "bold"),
            padding=5
        )
        style.map("Send.TButton", background=[("active", "#ff6b8e")])

        style.configure(
            "Path.TButton",
            background="#c0a0e0",
            foreground="#ffffff",
            font=("微软雅黑", 8),
            padding=3
        )
        style.map("Path.TButton", background=[("active", "#a880d8")])

    def _choose_rpg_dir(self):
        selected_dir = filedialog.askdirectory(
            title="选择RPG配置文件保存目录",
            initialdir=self.rpg_save_dir
        )
        if selected_dir:
            self.rpg_save_dir = selected_dir
            self._add_history("系统提示", f"RPG文件保存路径已设置为：\n{selected_dir}")
            logging.info(f"RPG保存路径已更新为：{selected_dir}")

    def _add_history(self, sender, content, is_loading=False):
        """添加历史记录，区分不同类型消息"""
        self.history_text.config(state=tk.NORMAL)
        content = re.sub(r'\n+', '\n', content)  # 清理多余空行

        # 选择标签
        if sender == "主人":
            tag = "user_tag"
        elif sender == "猫娘":
            tag = "assistant_tag"
        elif sender == "系统提示":
            tag = "loading_tag" if is_loading else "system_tag"
        else:
            tag = "system_tag"

        # 记录加载提示位置
        if is_loading:
            self.loading_start_pos = self.history_text.index(tk.END)

        # 新消息前添加空行（除第一条）
        if self.history_text.index(tk.END) != "1.0":
            self.history_text.insert(tk.END, "\n")

        # 插入内容
        self.history_text.insert(tk.END, f"【{sender}】 {content}\n", tag)

        self.history_text.config(state=tk.DISABLED)
        self.history_text.see(tk.END)

    def _on_enter_send(self, event):
        if event.state & 0x10:  # Shift+Enter换行
            return None
        else:  # Enter发送
            self._handle_send()
            return "break"

    def _handle_send(self):
        """发送消息处理逻辑"""
        user_input = self.input_text.get("1.0", tk.END).strip()
        if not user_input:
            return

        # 清空输入框并添加用户消息
        self.input_text.delete("1.0", tk.END)
        self._add_history("主人", user_input)
        # 添加加载提示
        self._add_history("系统提示", "正在思考中，请稍候...", is_loading=True)
        # 禁用发送按钮
        self.send_btn.config(state=tk.DISABLED)

        # 启动后台线程处理请求
        threading.Thread(
            target=self._process_request,
            args=(user_input,),
            daemon=True
        ).start()

    def _process_request(self, user_input):
        """后台处理请求"""
        try:
            # 调用对话中枢处理请求（传入RPG保存路径）
            response = self.assistant.handle_request(user_input, output_dir=self.rpg_save_dir)

            # 服务状态提示
            if "Ollama" in response and "没启动" in response:
                self.root.after(0, self._show_ollama_warning)
            if "RagFlow" in response and "没启动" in response:
                self.root.after(0, self._show_ragflow_warning)

        except Exception as e:
            response = f"处理请求时出错：{str(e)[:100]}..."
            logging.error(response)

        # 主线程更新UI
        self.root.after(0, self._update_response, response)

    def _update_response(self, response):
        """更新AI回复，删除加载提示"""
        self.history_text.config(state=tk.NORMAL)

        # 精确删除加载提示
        if self.loading_start_pos:
            self.history_text.delete(self.loading_start_pos, tk.END)
            self.loading_start_pos = None

        self.history_text.config(state=tk.DISABLED)
        response = re.sub(r'\n+', '\n', response)
        # 添加AI回复并恢复按钮状态
        self._add_history("猫娘", response)
        self.send_btn.config(state=tk.NORMAL)

    def _show_ollama_warning(self):
        messagebox.showwarning(
            "提示",
            "Ollama服务未启动！\n请先运行 `ollama serve` 启动服务，再使用助手~"
        )

    def _show_ragflow_warning(self):
        messagebox.showwarning(
            "提示",
            "RagFlow服务未启动！\n请先启动Docker容器，再使用知识库功能~"
        )


if __name__ == "__main__":
    root = tk.Tk()
    app = CatgirlGUI(root)
    root.mainloop()